package com.yxx.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
 * 线程工具类
 * @author yuxiangxun
 * @date 2025/1/18
 * @apiNote
 */
public class ThreadUtils {

    // 日志记录器实例
    private static final Logger logger = LoggerFactory.getLogger(ThreadUtils.class);

    private static final Long OVERTIME = 120L;


    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍然超時，則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     * @param pool
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
        if(pool != null && !pool.isShutdown()){
            // 先停止接收新任务并尝试完成所有已存在的任务
            pool.shutdown();
            try{
                // 等待60秒，如果超时，则调用shutdownNow
                if(!pool.awaitTermination(OVERTIME, TimeUnit.SECONDS)){
                    pool.shutdownNow();
                    // 再等待60秒，如果超时，打印日志信息“Pool did not terminate”
                    if(!pool.awaitTermination(OVERTIME, TimeUnit.SECONDS)){
                        logger.info("Pool did not terminate");
                    }
                }
            }catch (InterruptedException ie){
                // 如果当前线程被中断，则调用shutdownNow
                pool.shutdownNow();
                // 恢复当前线程的中断状态
                Thread.currentThread().interrupt();
            }
        }
    }


    /**
     * 打印异常信息
     *
     * 该方法用于处理和记录由 {@code Runnable} 或 {@code Future} 引发的异常。
     * 如果传入的 {@code Throwable} 对象为空，并且 {@code Runnable} 实际上是一个 {@code Future}，
     * 则尝试从 {@code Future} 中获取结果并捕获可能抛出的异常。
     * 最终，如果存在异常，则将其记录到日志中。
     *
     * @param r 可能引发异常的任务（通常是一个实现了 {@code Runnable} 接口的对象）
     * @param t 已知的异常对象（可以为空）
     */
    public static void printException(Runnable r, Throwable t){
        // 如果没有传入异常，并且任务实际上是一个 Future
       if(t == null && r instanceof Future<?>){
           try{
               Future<?> future = (Future<?>) r;
               // 如果Future任务已经完成，则尝试获取其结果
               if(future.isDone()){
                   future.get();
               }
           }catch (CancellationException ce){
               // 如果Future任务被取消，则记录CancellationException
               t = ce;
           }catch (ExecutionException ee){
               // 如果Future任务执行失败，则记录其原因
               t = ee.getCause();
           }catch (InterruptedException ie){
               // 如果线程在等待、定时等待、中断或执行过程中被中断，则恢复中断状态
               Thread.currentThread().interrupt();
           }
       }
       // 如果有异常需要记录，则使用日志记录器记录异常信息
       if(t != null){
           logger.error(t.getMessage(), t);
       }
    }
}
